package com.example.demo.utils;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.relational.Between;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
import net.sf.jsqlparser.statement.select.SetOperationList;
import net.sf.jsqlparser.statement.update.Update;

import java.util.ArrayList;
import java.util.List;

public class JSqlParser53Demo {

    private static final List<String> sqlList = new ArrayList<>();

    public static void main(String[] args) {
        fillSqlList();
        parseAllSql();
    }

    public static void fillSqlList() {
        sqlList.add("SELECT id AS userId, name FROM users WHERE age > 18");
        sqlList.add("WITH regional_sales AS (SELECT region, SUM(amount) AS total_sales FROM orders GROUP BY region) SELECT * FROM regional_sales WHERE total_sales > 100000");
    }

    public static void parseAllSql() {
        sqlList.forEach(sql -> {
            System.out.println("=".repeat(60));
            System.out.println("解析 SQL: " + sql);
            System.out.println("-".repeat(60));

            try {
                Statement statement = CCJSqlParserUtil.parse(sql);
                statement.accept(new TopLevelVisitor()); // 顶级访问者
            } catch (JSQLParserException e) {
                System.err.println("❌ 解析失败: " + e.getMessage());
            }

            System.out.println("=".repeat(60) + "\n");
        });
    }

    /**
     * 顶级语句访问者（处理 SELECT/INSERT/UPDATE/DELETE）
     */
    private static class TopLevelVisitor extends StatementVisitorAdapter<Void> {
        @Override
        public void visit(Select select) {
            System.out.println("[SELECT 语句]");
            select.accept(new SelectVisitorImpl(), 0); // 传递缩进层级
        }

        @Override
        public void visit(Insert insert) {
            System.out.println("[INSERT 语句]");
            System.out.println("  目标表: " + insert.getTable().getName());
        }

        @Override
        public void visit(Update update) {
            System.out.println("[UPDATE 语句]");
            System.out.println("  目标表: " + update.getTable().getName());
        }

        @Override
        public void visit(Delete delete) {
            System.out.println("[DELETE 语句]");
            System.out.println("  目标表: " + delete.getTable().getName());
        }
    }

    /**
     * SELECT 语句访问者（处理 SELECT 内部结构）
     */
    private static class SelectVisitorImpl extends SelectVisitorAdapter<Void> {
        private final int indent;

        public SelectVisitorImpl(int indent) {
            this.indent = indent;
        }

        public SelectVisitorImpl() {
            this(0);
        }

        @Override
        public void visit(PlainSelect plainSelect) {
            printIndent(indent);
            System.out.println("├─ 基础 SELECT:");
            printIndent(indent + 2);
            System.out.println("│  ├─ 主表: " + plainSelect.getFromItem());

            // 处理 JOIN
            if (plainSelect.getJoins() != null) {
                plainSelect.getJoins().forEach(join -> {
                    printIndent(indent + 2);
                    System.out.println("│  ├─ JOIN 类型: " + join);
                    printIndent(indent + 2);
                    System.out.println("│  └─ JOIN 表: " + join.getRightItem());
                });
            }

            // 处理 WHERE 条件
            if (plainSelect.getWhere() != null) {
                printIndent(indent + 2);
                System.out.println("│  └─ WHERE 条件: " + formatExpression(plainSelect.getWhere()));
            }
        }

        @Override
        public void visit(SetOperationList setOp) {
            printIndent(indent);
            System.out.println("├─ 集合操作 (UNION):");
            printIndent(indent + 2);
            System.out.println("│  ├─ 操作类型: " + setOp.getOperation(0));
            printIndent(indent + 2);
            System.out.println("│  └─ 子查询数量: " + setOp.getSelects().size());

            setOp.getSelects().forEach(subSelect ->
                subSelect.accept(new SelectVisitorImpl(indent + 2), null)
            );
        }

        // 表达式格式化工具
        private String formatExpression(Expression expr) {
            if (expr instanceof Between) {
                Between between = (Between) expr;
                return String.format("%s BETWEEN %s AND %s",
                        formatExpression(between.getLeftExpression()),
                        formatExpression(between.getBetweenExpressionStart()),
                        formatExpression(between.getBetweenExpressionEnd()));
            } else if (expr instanceof InExpression) {
                InExpression in = (InExpression) expr;
                return String.format("%s IN (%s)",
                        formatExpression(in.getLeftExpression()),
                        in.getRightExpression());
            }
            return expr.toString();
        }

        // 缩进工具
        private void printIndent(int level) {
            for (int i = 0; i < level; i++) {
                System.out.print("  ");
            }
        }
    }
}
